import tkinter as tk


class Layout:

    def __init__(self):
        pass


class Pack(Layout):

    def __init__(self):
        '''设置组件是否向水平或垂直方向填充|X、Y、BOTH 和NONE|fill = X（水平方向填充）fill = Y（垂直方向填充）fill = BOTH（水平和垂直）NONE 不填充'''
        self.fill = tk.BOTH
        '''设置组件是否展开，当值为YES时，side选项无效。组件显示在父容器中心位置；若fill选项为BOTH,则填充父组件的剩余空间。默认为不展开|	YES 、NO（1、0）|	expand=YES expand=NO'''
        self.expand = tk.NO
        '''side	设置组件的对齐方式|	LEFT、TOP、RIGHT、BOTTOM	|值为左、上、右、下'''
        self.side = tk.LEFT
        '''ipadx、ipady	设置x方向（或者y方向）内部间隙（子组件之间的间隔）	可设置数值，默认是0	非负整数，单位为像素
padx、pady	设置x方向（或者y方向）外部间隙（与之并列的组件之间的间隔）	可设置数值，默认是0	非负整数，单位为像素'''
        self.marginX = 0
        self.marginY = 0
        self.paddingX = 0
        self.paddingY = 0
        '''anchor	锚选项，当可用空间大于所需求的尺寸时，决定组件被放置于容器的何处	N、E、S、W、NW、NE、SW、SE、CENTER（默认值为CENTER）	表示八个方向以及中心'''
        self.anchor = tk.CENTER

    def v(self, fill=None, expand=None, marginX=0, marginY=0, paddingX=0, paddingY=0, anchor=None):
        if fill is not None:
            self.fill = fill
        if expand is not None:
            self.expand = expand
        if marginX is not None:
            self.marginX = marginX
        if marginY is not None:
            self.marginY = marginY
        if paddingX is not None:
            self.paddingX = paddingX
        if paddingY is not None:
            self.paddingY = paddingY
        if anchor is not None:
            self.anchor = anchor
        return self

    def bind(self, c):
        c.pack(fill=self.fill, expand=self.expand, padx=self.marginX, pady=self.marginY, ipadx=self.paddingX,
               ipady=self.paddingY, anchor=self.anchor)


class Grid(Layout):
    def __init__(self):
        '''
        row、column	row为行号，column为列号，设置将组件放置于第几行第几列	取值为行、列的序号，不是行数与列数
        row 和 column 的序号从0开始，但是，column的默认值是0，row的默认值是下一个编号较大的未占用行号
        '''
        self.row = 0
        self.column = 0
        '''sticky	设置组件在网格中的对齐方式（前提是有额外的空间）	N、E、S、W、NW、NE、SW、SE	类似于pack布局中的锚选项
        拉伸小控件

sticky=tk.N+tk.S 垂直拉伸小控件，并保持水平居中，其等价于字符串值"ns"，以下同

sticky=tk.E+tk.W 水平拉伸且持垂直居中

sticky=tk.N+tk.E+tk.S+tk.W 水平和垂直拉伸，等价于常量tk.NSEW和字符串值nsew

sticky=tk.N+tk.S+tk.W 将垂直拉伸并向西（左）对齐
        
        '''
        self.anchor = tk.N #+ tk.E + tk.S + tk.W
        '''rowspan	组件所跨越的行数	默认值为1	取值为跨越占用的行数，而不是序号'''
        self.rowspan = 1
        '''columnspan	组件所跨越的列数	默认值为1	取值为跨越占用的列数，而不是序号'''
        self.columnspan = 1
        '''ipadx、ipady	设置x方向（或者y方向）内部间隙（子组件之间的间隔）	可设置数值，默认是0	非负整数，单位为像素
       padx、pady	设置x方向（或者y方向）外部间隙（与之并列的组件之间的间隔）	可设置数值，默认是0	非负整数，单位为像素'''
        self.marginX = 0
        self.marginY = 0
        self.paddingX = 0
        self.paddingY = 0

    def v(self, row=None, column=None, marginX=0, marginY=0, paddingX=0, paddingY=0, anchor=None,
          rowspan=None, columnspan=None
          ):
        if row is not None:
            self.row = row
        if column is not None:
            self.column = column
        if marginX is not None:
            self.marginX = marginX
        if marginY is not None:
            self.marginY = marginY
        if paddingX is not None:
            self.paddingX = paddingX
        if paddingY is not None:
            self.paddingY = paddingY
        if anchor is not None:
            self.anchor = anchor
        if rowspan is not None:
            self.rowspan = rowspan
        if columnspan is not None:
            self.columnspan = columnspan
        return self

    def bind(self, c):
        c.grid(row=self.row, column=self.column,
               padx=self.marginX, pady=self.marginY, ipadx=self.paddingX,
               ipady=self.paddingY, sticky=self.anchor,
               rowspan=self.rowspan, columnspan=self.columnspan
               )

class Place(Layout):

    def __init__(self):
        self.anchor = tk.NW  # + tk.E + tk.S + tk.W
        self.x=0
        self.y=0
        self.relx =0
        self.rely=0
        self.width=20
        self.height=20
        self.relWidth=0
        self.relHeight=0
        '''
        bordermode	如果设置为INSIDE，组件内部的大小和位置是相对的，不包括边框；如果是OUTSIDE，组件的外部大小是相对的，包括边框	INSIDE、OUTSIDE(默认值INSIDE)	可以使用常量INSIDE、OUTSIDE，也可以使用字符串形式"inside"、"outside"
        '''
        self.bordermode=tk.INSIDE


    def v(self, x=None, y=None, relx=0, rely=0, width=0, height=0, anchor=None,
          relWidth=None, relHeight=None,bordermode=None
          ):
        if x is not None:
            self.x = x
        if y is not None:
            self.y = y
        if relx is not None:
            self.relx = relx
        if rely is not None:
            self.rely = rely
        if width is not None:
            self.width = width
        if height is not None:
            self.height = height
        if anchor is not None:
            self.anchor = anchor
        if relWidth is not None:
            self.relWidth = relWidth
        if relHeight is not None:
            self.relHeight = relHeight
        if bordermode is not None:
            self.bordermode = bordermode
        return self
    def bind(self, c):
        c.place(x=self.x, y=self.y,
               relx=self.relx, rely=self.rely, width=self.width,
               height=self.height, anchor=self.anchor,
               relheight=self.relHeight, relwidth=self.relWidth,bordermode=self.bordermode
               )
